package com.cloud.common.magic_init.handler;

import cn.hutool.crypto.SecureUtil;
import com.cloud.common.enums.DeveloperState;
import com.cloud.common.enums.RoleAuthState;
import com.cloud.common.magic_init.service.RedisMagicService;
import com.cloud.magic_api.entity.LoginUserInfo;
import com.cloud.magic_api.entity.SysUserInfo;
import com.cloud.magic_api.mapper.SysRoleAuthMapper;
import com.cloud.magic_api.mapper.SysUserInfoMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;
import org.ssssssss.magicapi.core.context.MagicUser;
import org.ssssssss.magicapi.core.exception.MagicLoginException;
import org.ssssssss.magicapi.core.interceptor.Authorization;
import org.ssssssss.magicapi.core.interceptor.AuthorizationInterceptor;
import org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest;

/**
 * 登录认证拦截
 *
 * @author yzj
 */
@Component
public class MagicAuthorization implements AuthorizationInterceptor {

    @Resource
    private SysUserInfoMapper sysUserInfoMapper;

    @Resource
    private SysRoleAuthMapper sysRoleAuthMapper;

    @Resource
    private RedisMagicService redisMagicService;

    // 配置是否需要登录
    @Override
    public boolean requireLogin() {
        return true;
    }

    // 验证Magic 用户登录Token 有效性
    @Override
    public MagicUser getUserByToken(String token) throws MagicLoginException {
        LoginUserInfo loginUser = redisMagicService.getDeveloperUser(token);
        if (ObjectUtils.isNotEmpty(loginUser)) {
            // 验证Token 是否失效
            redisMagicService.verifyToken(loginUser);
            return new MagicUser(loginUser.getDeveloper().getId() + "-" + loginUser.getDeveloper().getUserName(),
                    loginUser.getDeveloper().getNickName(), loginUser.getToken());
        }
        throw new MagicLoginException("验证失败:Token已失效或未登录");
    }

    /**
     * Magic登录查询
     *
     * @param username
     * @param password
     * @return
     * @throws MagicLoginException
     */
    @Override
    public MagicUser login(String username, String password) throws MagicLoginException {
        SysUserInfo loginUser = sysUserInfoMapper.userLogin(username, SecureUtil.md5(password));
        if (ObjectUtils.isNotEmpty(loginUser)) {
            if (DeveloperState.DISABLE.getCode().equals(loginUser.getState())) {
                throw new MagicLoginException("账户已停用,请联系管理员");
            } else {
                LoginUserInfo developerUser = new LoginUserInfo();
                developerUser.setDeveloper(loginUser);
                // 获取角色权限信息
                developerUser.setRoleAuth(sysRoleAuthMapper.selectById(loginUser.getRoleId()));
                // 缓存 Magic开发者信息
                String token = redisMagicService.createToken(developerUser);
                MagicUser userInfo = new MagicUser();
                userInfo.setId(loginUser.getId() + "-" + loginUser.getUserName());
                userInfo.setUsername(loginUser.getNickName());
                userInfo.setToken(token);
                return userInfo;
            }
        }
        throw new MagicLoginException("账户不存在,请检查账户信息是否正确");
    }

    /**
     * 是否拥有页面按钮的权限
     */
    @Override
    public boolean allowVisit(MagicUser magicUser, MagicHttpServletRequest request, Authorization authorization) {
        LoginUserInfo loginUser = redisMagicService.getDeveloperUser(magicUser);
        if (RoleAuthState.ADMIN.getCode().equals(loginUser.getRoleAuth().getPermission())) {
            return true;
        } else if (RoleAuthState.DEVELOPER.getCode().equals(loginUser.getRoleAuth().getPermission())) {
            if (Authorization.LOCK.name().equals(authorization.name())
                    || Authorization.UNLOCK.name().equals(authorization.name())
                    || Authorization.PUSH.name().equals(authorization.name())) {
                return false;
            }
        }
        return true;
    }

    /**
     * 推出登录
     *
     * @param token
     */
    @Override
    public void logout(String token) {
        redisMagicService.removeDeveloperUser(token);
    }

}
